Skip to content

Add compass probe helper functions#31606

Merged
peterbarker merged 5 commits into
ArduPilot:masterfrom
peterbarker:pr/compass-helpers
Dec 10, 2025
Merged

Add compass probe helper functions#31606
peterbarker merged 5 commits into
ArduPilot:masterfrom
peterbarker:pr/compass-helpers

Conversation

@peterbarker
Copy link
Copy Markdown
Contributor

@peterbarker peterbarker commented Nov 27, 2025

(and adjust backends to take HAL::Device rather than HAL::I2CDevice)

This is primarily to reduce the number of calls to i2c_mgr->get_device and hal.spi->get_device so moving away from OwnPtr is easier.

However, we also:

  • remove memory leaks when driver disabled (the check for enablement is done inside add_backend, and we don't free the allocated backend if the thing is disabled via parameter
  • save flash
  • allow for more refactoring of the probing to avoid the FOR_EACH code generation
Board                    AP_Periph  blimp  bootloader  copter  heli   iofirmware  plane  rover  sub
CubeOrange-periph-heavy  -2160             *                                                    
Durandal                            -2136  *           -2136   -2136              -2136  -2136  -2136
Hitec-Airspeed           *                 *                                                    
KakuteH7-bdshot                     -2064  *           -2064   -2072              -2064  -2064  -2064
MatekF405                           -1816  *           -1824   -1816              -1816  -1816  -1816
Pixhawk1-1M-bdshot                  -1896              -1888   -1888              -1896  -1896  -1896
SITL_x86_64_linux_gnu               *                  *       *                  *      *      *
f103-QiotekPeriph        0                 *                                                    
f303-MatekGPS            0                 *                                                    
f303-Universal           -1448             *                                                    
iomcu                                                                 *                         
revo-mini                           0      *           0       0                  0      0      0
skyviper-v2450                                         0                                        
speedybeef4                         -1816  *           -1816   -1824              -1816  -1816  -1816

@peterbarker
Copy link
Copy Markdown
Contributor Author

Tested on a CubeOrange with an external HMC5883
Tested on a CUAV V6X with an external RM3100
Tested on a Durandal with an external IST8310
Tested on a CubeBlack with an external HMC5883
Tested on a CubeBlack with an external QMC5883L

@peterbarker
Copy link
Copy Markdown
Contributor Author

CubeOrange-periph-heavy:
image
image
image

Example of OwnPtr bloat:
image

@peterbarker peterbarker moved this to ReadyForDevCall in Peter's ArduPilot 4.8 Queue Dec 8, 2025
Copy link
Copy Markdown
Contributor

@tridge tridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to think about how to validate this PR, tricky!

Comment thread libraries/AP_Compass/AP_Compass.cpp Outdated
return;
}
auto *backend = AP_Compass_AK09916::probe_ICM20948(
GET_I2C_DEVICE(i2c_bus, HAL_COMPASS_AK09916_I2C_ADDR),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not using the address arguments

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment thread libraries/AP_Compass/AP_Compass.cpp Outdated

#endif // #if AP_COMPASS_AK09916_ENABLED && AP_COMPASS_ICM20948_ENABLED

void Compass::probe_i2c_dev(DriverType driver_type, AP_Compass_Backend* (*probefn)(AP_HAL::OwnPtr<AP_HAL::Device>, bool, Rotation), uint8_t i2c_bus, uint8_t i2c_addr, bool external, Rotation rotation)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should typedef a function ptr for this, maybe AP_Compass::probe_i2c_fn_t ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 3x aliases for that mess.

Comment thread libraries/AP_Compass/AP_Compass.cpp Outdated
add_backend(driver_type, backend); // add_backend does nullptr check
}

void Compass::probe_spi_dev(DriverType driver_type, AP_Compass_Backend* (*probefn)(AP_HAL::OwnPtr<AP_HAL::Device>, bool, Rotation), const char *name, bool external, Rotation rotation)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe AP_Compass::probe_spi_ext_fn_t ?

Copy link
Copy Markdown
Contributor

@tridge tridge Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does it make sense to have an external bool on an SPI device?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! We will find out as more cleanups emerge. Which they will.

.... also, I don't think there's any reason you couldn't have a compass connected externally via SPI...

Comment thread libraries/AP_Compass/AP_Compass.cpp Outdated

// short-lived method which expectes a probe function that doesn't
// offer the ability to specify an external rotation:
void Compass::probe_spi_dev(DriverType driver_type, AP_Compass_Backend* (*probefn)(AP_HAL::OwnPtr<AP_HAL::Device>, Rotation), const char *name, Rotation rotation)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe AP_Compass::probe_spi_fn_t ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 3x probe aliases

@peterbarker peterbarker force-pushed the pr/compass-helpers branch 2 times, most recently from cb926d5 to 4630bed Compare December 9, 2025 00:26
Copy link
Copy Markdown
Contributor

@tpwrules tpwrules left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You missed DRIVER_MMC5XX3.

Other than that everything matches up. I printed the PR out on paper and checked with a pen that everything lined up! Would be happy to merge after that one is fixed.

Cleanup ideas (not mandatory):

  • fix the comment on LIS3MDL bus number while in there
  • there are several HAL_COMPASS_*_ORIENTATION_INTERNAL that can't be used e.g. QMC5883P as all_external is guaranteed true
  • if we use helper methods or adjust the other add_backend invocations we can fully prevent leaks and drop the enabled check in it
  • 90% of these could be packed into a struct and iterated over in one loop. Presumably this is what you were suggesting on the call? Preserving ordering might be tricky.

@peterbarker
Copy link
Copy Markdown
Contributor Author

You missed DRIVER_MMC5XX3.

Ah, late entry. Fixed.

Other than that everything matches up. I printed the PR out on paper and checked with a pen that everything lined up! Would be happy to merge after that one is fixed.

Thanks!

Cleanup ideas (not mandatory):

* fix the comment on LIS3MDL bus number while in there

Future PR. There are actually a bunch of incorrect comments floating around IIRC.

* there are several `HAL_COMPASS_*_ORIENTATION_INTERNAL` that can't be used e.g. QMC5883P as `all_external` is guaranteed true

Yes, and there's the inconsistency with the SPI compasses too which should be addressed!

* if we use helper methods or adjust the other `add_backend` invocations we can fully prevent leaks and drop the enabled check in it

In Baro I ended up with something like a probe_dev - but that was near enough to add_backend that I don't know if it will go away or not.

* 90% of these could be packed into a struct and iterated over in one loop. Presumably this is what you were suggesting on the call? Preserving ordering might be tricky.

Yes, I've done that and it does work quite nicely. I have a branch here somewhere.

I've actually tried two different flavours of that, one which uses static const structures and one that doesn't.

all_external is a blight.

@peterbarker peterbarker merged commit 096d240 into ArduPilot:master Dec 10, 2025
107 checks passed
@github-project-automation github-project-automation Bot moved this from ReadyForDevCall to Done in Peter's ArduPilot 4.8 Queue Dec 10, 2025
@peterbarker peterbarker deleted the pr/compass-helpers branch December 10, 2025 10:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants